Random no generator of 8086 getrand: ; Destroys all main registers, returns AXBX = 32-bit random number ; Also returns EBX = 32-bit random number on 80386 %ifdef CPU_80386 ; 80386 version (32-bit, has barrel-shifter, fast!) mov eax, [randx] ; Ahh, 32-bit registers... mov ebx, eax ; Does this save us a memory access on the XOR? shl eax, 11 ; Ahh, barrel-shifter with large immediate shifts... xor eax, ebx mov ebx, [randw] ; I'm not going to try to make the list-shuffle look mov ecx, [randy] ; like it corresponds, important thing is that the mov [randx], ecx ; values wind up in the right place. mov ecx, [randz] mov [randy], ecx mov [randz], ebx mov ecx, ebx shr ecx, 19 xor ebx, ecx mov ecx, eax shr ecx, 8 xor eax, ecx xor ebx, eax mov [randw], ebx ; Now load the high word of EBX into AX, for compatibility mov eax, ebx ; I need to get a better 386 assembler reference, shr eax, 16 ; but I don't believe there's a way to access the ; high word of a 32-bit register directly... %else ; 8086 version (much slower, but more explanatorily commented!) ; Many steps are done out of order here in order to minimize re-loading ; of values from memory. I *think* I've tracked everything correctly so ; that the results are correct. mov cx, [randx+2] ; CXDX = [randx] mov dx, [randx] mov ah, cl ; AXBX = [randx] << 8 mov al, dh mov bh, dl xor bl, bl shl bx, 1 ; AXBX = AXBX << 3 rcl ax, 1 shl bx, 1 rcl ax, 1 shl bx, 1 rcl ax, 1 xor ax, cx ; First part of the algorithm: xor bx, dx ; t = (x XOR (x << 11)) mov dl, bh ; CXDX = (t >> 8) mov dh, al mov cl, ah xor ch, ch xor ax, cx ; Piece for the second part of the algorithm: xor bx, dx ; (t XOR (t >> 8)) mov cx, [randy+2] ; Move the stored values one space along in the list mov dx, [randy] ; X = Y, Y = Z, Z = W mov [randx+2], cx mov [randx], dx ; Is this the fastest way to do it? Seems like it mov cx, [randz+2] ; would be, I can't think of another method that mov dx, [randz] ; requires fewer memory accesses and no overhead. mov [randy+2], cx mov [randy], dx mov dx, [randw+2] ; DX = [randw] >> 16 (for later) mov cx, [randw] mov [randz+2], dx mov [randz], cx xor ax, dx ; Cuts the final XOR in half. shr dx, 1 ; DX = DX >> 3 shr dx, 1 shr dx, 1 xor dx, cx ; Piece for the second part of the algorithm: ; (w XOR (w >> 19)) xor bx, dx ; Second part: ; w = (w XOR (w >> 19)) XOR (t XOR (t >> 8)) ; return w mov [randw], bx ; Final history-list operation, store new value in W mov [randw+2], ax %endif ret ; Put these anywhere, but have 'em aligned! alignb 4 randx: resd 1 randy: resd 1 randz: resd 1 randw: resd 1 Assembly Language Program to multiply two 32-bit unsigned numbers. MODEL SMALL .STACK 100 .DATA ; Data segment starts A DW 5678H, 1234H, 5 DUP(0) ;A is 32bit number A=1234 5678 b DW 1111H, 1111H, 5 DUP(0) ;B is 32bit number B=1111 1111 C DW 4 DUP(?) ; Reserve 4 words of uninitialized data space to an offset C .CODE START: MOV AX,@DATA ;Initialize DS MOV DS,AX MOV SI,OFFSET A ;Point to first number in A MOV AX,WORD PTR A[SI] ;Take lower 16bits(5678) of A into AX MUL WORD PTR B[BX+0] ;Multiply AX with lower 16bits of B(1111) and store in AX MOV C[DI],AX ;Move the contents of AX to C[DI] MOV CX,DX ;Move the value of DX to CX MOV AX,WORD PTR A[SI+2] ;Take higher 16bits(1234) of A into AX MUL WORD PTR B[BX+0] ;Multiply AX with lower 16bits of B(1111)and store in AX ADD CX,AX ;CX=CX+AX MOV C[DI+2],CX ;Move the contents of CX to C[DI+2] MOV CX,DX ;Move contents of DX to CX MOV AX,WORD PTR A[SI] ;Take lower 16bits(5678) of A in AX MUL WORD PTR B[BX+2] ;Multiply contents of AX with higher 16bits of B(1111) ADD WORD PTR C[DI+2],AX ;C[DI+2]=C[DI+2]+AX ADC CX,DX ;CX=CX+DX+CF MOV C[DI+4],AX ;Move contents of AX to C[DI+4] MOV AX,WORD PTR A[SI+2] ;Take higher 16bits of A(1234) into AX MUL WORD PTR B[BX+2] ;Multiply AX with higher 16bits of B(1111) and store in AX ADD CX,AX ;CX=CX+AX MOV WORD PTR C[DI+4],CX ;Move contents of CX to C[DI+4] ADC DX,0000 ;DX=DX+0000+CF MOV C[DI+6],DX ;Move the contents of DX to C[DI+6] INT 03H ; Halt END START Assembly Language Program to div two unsigned numbers. MODEL SMALL .STACK 100 .DATA ; Data Segment to initialize the variables Dividend DW 1234H, 5678H ; Dividend = 1234 5678 H Divisor DW 270FH ; Divisor = 207FH Quotient DW ? ; Variable Quotient to store Quotient Reminder DW ? ; Variable Reminder to store Reminder .CODE START: MOV AX,@DATA MOV DS,AX ;Initialize data segment MOV SI,0000H ;Initialize SI to 0000H MOV DX,Dividend[SI] ;Take higher 16-bit number which is to be divided in DX register MOV AX,Dividend[SI+2] ;Take lower 16-bit number which is to be divided in AX register MOV CX,Divisor ;Take divisor in CX register DIV CX ; Performs unsigned Division DX:AX ÷CX ; AX = Quotient DX = Reminder MOV Reminder,DX ;Store Reminder MOV Quotient,AX ;Store Quotient INT 03H END START